<?php declare(strict_types=1);

namespace App\WebSocket\Business;

use Swoft\Session\Session;
use Swoft\Redis\Redis;
use App\Model\SystemMessageUser;

/**
 * 消息通知-业务类
 * Class MessageBusiness
 * @package App\WebSocket\Business
 */
class MessageBusiness
{
        /**
         * 绑定用户
         * @return void
         */
        public static function bind(): void
        {
                $arrParam = request()->getMessage()->toArray();
                $strToken = str_replace('Bearer ', '', $arrParam['data']['token']);
                if (!$strToken) {
                        $arrReturn = callbackParam(403, false, [], 'token can not be empty!');
                        Session::current()->push(json_encode($arrReturn, JSON_UNESCAPED_UNICODE));
                        return;
                }
                $arrTokenData = json_decode(decryptOpenssl($strToken, SSL_KEY, SSL_IV), true);
                if (!$arrTokenData) {
                        $arrReturn = callbackParam(403, false, [], 'token validation fails!');
                        Session::current()->push(json_encode($arrReturn, JSON_UNESCAPED_UNICODE));
                        return;
                }
                $intFd = request()->getFrame()->fd;
                $strUserId = $arrTokenData['userId'];
                Redis::set('MessageFd_' . $strUserId . '_' . $intFd, $intFd, 35);
                $arrWhere = ['userId' => $strUserId, 'isRead' => 2];
                $intNotReadTotal = SystemMessageUser::getTotal($arrWhere);
                $arrParam['data'] = ['fd' => $intFd, 'notReadTotal' => $intNotReadTotal];
                $arrReturn = callbackParam(0, true, $arrParam, 'bind success!');
                Session::current()->push(json_encode($arrReturn, JSON_UNESCAPED_UNICODE));
        }

        /**
         * 心跳检测是否保持连接
         * @return void
         */
        public static function heartbeat(): void
        {
                $arrParam = request()->getMessage()->toArray();
                $strToken = str_replace('Bearer ', '', $arrParam['data']['token']);
                if (!$strToken) {
                        $arrReturn = callbackParam(403, false, [], 'token can not be empty!');
                        Session::current()->push(json_encode($arrReturn, JSON_UNESCAPED_UNICODE));
                        return;
                }
                $arrTokenData = json_decode(decryptOpenssl($strToken, SSL_KEY, SSL_IV), true);
                if (!$arrTokenData) {
                        $arrReturn = callbackParam(403, false, [], 'token validation fails!');
                        Session::current()->push(json_encode($arrReturn, JSON_UNESCAPED_UNICODE));
                        return;
                }
                $intFd = request()->getFrame()->fd;
                $strUserId = $arrTokenData['userId'];
                Redis::set('MessageFd_' . $strUserId . '_' . $intFd, $intFd, 35);
                $arrRedisKeys = Redis::keys('MessageFd_'. $strUserId.'_*');
                $arrReturn = callbackParam(0, true, $arrParam);
                foreach ($arrRedisKeys as $v) {
                        $arrUserFd = explode('_', $v);
                        $intFd = intval($arrUserFd[2]);
                        $bool = server()->sendTo($intFd, json_encode($arrReturn, JSON_UNESCAPED_UNICODE));
                        if (!$bool) {
                                Redis::del('MessageFd_' . $strUserId . '_' . $intFd);
                                server()->disconnect($intFd);
                        }
                }
        }

        /**
         * 获取信息
         * @return void
         */
        public static function fetch(): void
        {
                $arrParam = request()->getMessage()->toArray();
                $intFd = request()->getFrame()->fd;
                $strKey = Redis::keys('MessageFd_*_' . $intFd)[0];
                $strUserId = explode('_', $strKey)[1];
                $intPage = intval($arrParam['data']['page']);
                $intLimit = intval($arrParam['data']['limit']);
                $intType = intval($arrParam['data']['type']);
                $arrWhere = ['system_message_user.userId' => $strUserId, 'system_message.type' => $intType];
                $arrField = ['system_message.messageId', 'system_message.title', 'system_message.content', 'system_message.title', 'system_message.createTime'];
                $arrOrderBy = ['system_message.createTime' => 'DESC'];
                $arrJoin = [
                        'system_message' => [
                                'table' => 'system_message',
                                'where' => ['system_message.messageId', '=', 'system_message_user.messageId']
                        ]
                ];
                $arrResult = SystemMessageUser::getList($arrWhere, $arrField, $intPage, $intLimit, $arrOrderBy, [], $arrJoin);
                $arrWhere = [['whereIn', 'messageId', array_column($arrResult['list'], 'messageId')], 'userId' => $strUserId];
                $arrSet = ['isRead' => 1];
                SystemMessageUser::renewal($arrWhere, $arrSet);
                $arrWhere = ['userId' => $strUserId, 'isRead' => 2];
                $intNotReadTotal = SystemMessageUser::getTotal($arrWhere);
                $arrResult['notReadTotal'] = $intNotReadTotal;
                $arrParam['data'] = $arrResult;
                $arrReturn = callbackParam(0, true, $arrParam);
                Session::current()->push(json_encode($arrReturn, JSON_UNESCAPED_UNICODE));
        }

        /**
         * 重置未读总数
         * @return void
         */
        public static function resetNotReadTotal(): void
        {
                $arrParam = request()->getMessage()->toArray();
                $arrUserId = $arrParam['data']['userIds'];
                $arrMessageUserId = [];
                foreach ($arrUserId as $v) {
                        $arrUserFds = Redis::keys('MessageFd_' . $v . '_*');
                        if (!$arrUserFds) continue;
                        foreach ($arrUserFds as $v2) {
                                $arrUserFd = explode('_', $v2);
                                $strUserId = $arrUserFd[1];
                                $intFd = intval($arrUserFd[2]);
                                if (!isset($arrMessageUserId[$strUserId])) $arrMessageUserId[$strUserId] = [];
                                $arrMessageUserId[$strUserId][] = $intFd;
                        }
                }
                foreach ($arrMessageUserId as $k => $v) {
                        $arrWhere = ['userId' => $k, 'isRead' => 2];
                        $intNotReadTotal = SystemMessageUser::getTotal($arrWhere);
                        $arrParam['data'] = [
                                'notReadTotal' => $intNotReadTotal
                        ];
                        $arrReturn = callbackParam(0, true, $arrParam);
                        server()->sendToSome(json_encode($arrReturn, JSON_UNESCAPED_UNICODE), $v);
                }
        }
}